home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / sendmail-5.65c+IDA-1.4.4.1 / src / envelope.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-20  |  13.2 KB  |  599 lines

  1. /*
  2.  * Copyright (c) 1983 Eric P. Allman
  3.  * Copyright (c) 1988 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted provided
  7.  * that: (1) source distributions retain this entire copyright notice and
  8.  * comment, and (2) distributions including binaries display the following
  9.  * acknowledgement:  ``This product includes software developed by the
  10.  * University of California, Berkeley and its contributors'' in the
  11.  * documentation or other materials provided with the distribution and in
  12.  * all advertising materials mentioning features or use of this software.
  13.  * Neither the name of the University nor the names of its contributors may
  14.  * be used to endorse or promote products derived from this software without
  15.  * specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  17.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  18.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  */
  20.  
  21. #ifndef lint
  22. static char sccsid[] = "@(#)envelope.c    5.22 (Berkeley) 6/1/90";
  23. static char  rcsid[] = "@(#)$Id: envelope.c,v 5.22.0.14 1991/06/21 12:47:26 paul Exp $";
  24. #endif /* not lint */
  25.  
  26. #include "sendmail.h"
  27. #include <sys/stat.h>
  28. #include <pwd.h>
  29.  
  30. #ifdef __STDC__
  31. static void closexscript(ENVELOPE *);
  32. static bool trusteduser(const char *);
  33. #else /* !__STDC__ */
  34. static void closexscript();
  35. static bool trusteduser();
  36. #endif /* __STDC__ */
  37.  
  38. /*
  39. **  NEWENVELOPE -- allocate a new envelope
  40. **
  41. **    Supports inheritance.
  42. **
  43. **    Parameters:
  44. **        e -- the new envelope to fill in.
  45. **
  46. **    Returns:
  47. **        e.
  48. **
  49. **    Side Effects:
  50. **        none.
  51. */
  52.  
  53. ENVELOPE *
  54. newenvelope(e)
  55.     register ENVELOPE *e;
  56. {
  57.     register ENVELOPE *parent;
  58.  
  59.     parent = CurEnv;
  60.     if (e == CurEnv)
  61.         parent = e->e_parent;
  62.     clearenvelope(e, TRUE);
  63.     if (e == CurEnv)
  64.         bcopy((char *) &NullAddress, (char *) &e->e_from, sizeof e->e_from);
  65.     else
  66.         bcopy((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from);
  67.     e->e_parent = parent;
  68.     e->e_ctime = curtime();
  69.     e->e_msgpriority = parent->e_msgsize;
  70.     e->e_puthdr = putheader;
  71.     e->e_putbody = putbody;
  72.     if (CurEnv->e_xfp != NULL)
  73.         (void) fflush(CurEnv->e_xfp);
  74.  
  75.     return (e);
  76. }
  77. /*
  78. **  DROPENVELOPE -- deallocate an envelope.
  79. **
  80. **    Parameters:
  81. **        e -- the envelope to deallocate.
  82. **
  83. **    Returns:
  84. **        none.
  85. **
  86. **    Side Effects:
  87. **        housekeeping necessary to dispose of an envelope.
  88. **        Unlocks this queue file.
  89. */
  90.  
  91. void
  92. dropenvelope(e)
  93.     register ENVELOPE *e;
  94. {
  95.     bool queueit = FALSE;
  96.     register ADDRESS *q;
  97.  
  98.     if (tTd(50, 1))
  99.     {
  100.         printf("dropenvelope %x id=", e);
  101.         xputs(e->e_id);
  102.         printf(" flags=%o\n", e->e_flags);
  103.     }
  104. #ifdef LOG
  105.     if (LogLevel > 10)
  106.         syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=%o, pid=%d",
  107.                   e->e_id == NULL ? "(none)" : e->e_id,
  108.                   e->e_flags, getpid());
  109. #endif /* LOG */
  110.  
  111.     /* we must have an id to remove disk files */
  112.     if (e->e_id == NULL)
  113.         return;
  114.  
  115.     /*
  116.     **  Extract state information from dregs of send list.
  117.     */
  118.  
  119.     for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  120.     {
  121.         if (bitset(QQUEUEUP, q->q_flags))
  122.             queueit = TRUE;
  123.     }
  124.  
  125.     /*
  126.     **  Send back return receipts as requested.
  127.     */
  128.  
  129.     if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags))
  130.     {
  131.         auto ADDRESS *rlist = NULL;
  132.  
  133.         sendtolist(e->e_receiptto, (ADDRESS *) NULL, &rlist);
  134.         (void) returntosender("Return receipt", rlist, FALSE);
  135.     }
  136.  
  137.     /*
  138.     **  Arrange to send error messages if there are fatal errors.
  139.     */
  140.  
  141.     if (bitset(EF_FATALERRS|EF_TIMEOUT, e->e_flags) && ErrorMode != EM_QUIET)
  142.         savemail(e);
  143.  
  144.     /*
  145.     **  Instantiate or deinstantiate the queue.
  146.     */
  147.  
  148.     if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) ||
  149.         bitset(EF_CLRQUEUE, e->e_flags))
  150.     {
  151.         if (e->e_df != NULL)
  152.             xunlink(e->e_df);
  153.         xunlink(queuename(e, 'q'));
  154.     }
  155.     else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
  156.     {
  157. #ifdef QUEUE
  158.         FILE *lockfp;
  159.  
  160.         lockfp = queueup(e, FALSE, FALSE);
  161.         if (lockfp != NULL)
  162.             (void) fclose(lockfp);
  163. #else /* !QUEUE */
  164.         syserr("dropenvelope: queueup");
  165. #endif /* QUEUE */
  166.     }
  167.  
  168.     /* now unlock the job */
  169.     closexscript(e);
  170.     unlockqueue(e);
  171.  
  172.     /* make sure that this envelope is marked unused */
  173.     e->e_id = e->e_df = NULL;
  174.     if (e->e_dfp != NULL)
  175.         (void) fclose(e->e_dfp);
  176.     e->e_dfp = NULL;
  177. }
  178. /*
  179. **  CLEARENVELOPE -- clear an envelope without unlocking
  180. **
  181. **    This is normally used by a child process to get a clean
  182. **    envelope without disturbing the parent.
  183. **
  184. **    Parameters:
  185. **        e -- the envelope to clear.
  186. **        fullclear - if set, the current envelope is total
  187. **            garbage and should be ignored; otherwise,
  188. **            release any resources it may indicate.
  189. **
  190. **    Returns:
  191. **        none.
  192. **
  193. **    Side Effects:
  194. **        Closes files associated with the envelope.
  195. **        Marks the envelope as unallocated.
  196. */
  197.  
  198. void
  199. clearenvelope(e, fullclear)
  200.     register ENVELOPE *e;
  201.     bool fullclear;
  202. {
  203.     register HDR *bh;
  204.     register HDR **nhp;
  205.     extern ENVELOPE BlankEnvelope;
  206.  
  207.     if (!fullclear)
  208.     {
  209.         /* clear out any file information */
  210.         if (e->e_xfp != NULL)
  211.             (void) fclose(e->e_xfp);
  212.         if (e->e_dfp != NULL)
  213.             (void) fclose(e->e_dfp);
  214.     }
  215.  
  216.     /* now clear out the data */
  217.     STRUCTCOPY(BlankEnvelope, *e);
  218.     bh = BlankEnvelope.e_header;
  219.     nhp = &e->e_header;
  220.     while (bh != NULL)
  221.     {
  222.         *nhp = (HDR *) xalloc(sizeof *bh);
  223.         bcopy((char *) bh, (char *) *nhp, sizeof *bh);
  224.         bh = bh->h_link;
  225.         nhp = &(*nhp)->h_link;
  226.     }
  227. }
  228. /*
  229. **  INITSYS -- initialize instantiation of system
  230. **
  231. **    In Daemon mode, this is done in the child.
  232. **
  233. **    Parameters:
  234. **        none.
  235. **
  236. **    Returns:
  237. **        none.
  238. **
  239. **    Side Effects:
  240. **        Initializes the system macros, some global variables,
  241. **        etc.  In particular, the current time in various
  242. **        forms is set.
  243. */
  244.  
  245. void
  246. initsys()
  247. {
  248.     static char cbuf[5];            /* holds hop count */
  249.     static char pbuf[10];            /* holds pid */
  250. #ifdef TTYNAME
  251.     static char ybuf[10];            /* holds tty id */
  252.     register char *p;
  253. #endif /* TTYNAME */
  254.  
  255.     /*
  256.     **  Give this envelope a reality.
  257.     **    I.e., an id, a transcript, and a creation time.
  258.     */
  259.  
  260.     openxscript(CurEnv);
  261.     CurEnv->e_ctime = curtime();
  262.  
  263.     /*
  264.     **  Set OutChannel to something useful if stdout isn't it.
  265.     **    This arranges that any extra stuff the mailer produces
  266.     **    gets sent back to the user on error (because it is
  267.     **    tucked away in the transcript).
  268.     */
  269.  
  270.     if (OpMode == MD_DAEMON && QueueRun)
  271.         OutChannel = CurEnv->e_xfp;
  272.  
  273.     /*
  274.     **  Set up some basic system macros.
  275.     */
  276.  
  277.     /* process id */
  278.     (void) sprintf(pbuf, "%d", getpid());
  279.     define('p', pbuf, CurEnv);
  280.  
  281.     /* hop count */
  282.     (void) sprintf(cbuf, "%d", CurEnv->e_hopcount);
  283.     define('c', cbuf, CurEnv);
  284.  
  285.     /* time as integer, unix time, arpa time */
  286.     settime();
  287.  
  288. #ifdef TTYNAME
  289.     /* tty name */
  290.     if (macvalue('y', CurEnv) == NULL)
  291.     {
  292.         p = ttyname(2);
  293.         if (p != NULL)
  294.         {
  295.             if (rindex(p, '/') != NULL)
  296.                 p = rindex(p, '/') + 1;
  297.             (void) strcpy(ybuf, p);
  298.             define('y', ybuf, CurEnv);
  299.         }
  300.     }
  301. #endif /* TTYNAME */
  302. }
  303. /*
  304. **  SETTIME -- set the current time.
  305. **
  306. **    Parameters:
  307. **        none.
  308. **
  309. **    Returns:
  310. **        none.
  311. **
  312. **    Side Effects:
  313. **        Sets the various time macros -- $a, $b, $d, $t.
  314. */
  315.  
  316. void
  317. settime()
  318. {
  319.     register char *p;
  320.     auto time_t now;
  321.     static char tbuf[13];            /* holds "current" time */
  322.     static char dbuf[26];            /* holds ctime(tbuf) */
  323.     register struct tm *tm;
  324.  
  325.     now = curtime();
  326.     tm = gmtime(&now);
  327.     (void) sprintf(tbuf, "%04d%02d%02d%02d%02d", 1900 + tm->tm_year,
  328.         tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min);
  329.     define('t', tbuf, CurEnv);
  330.     (void) strcpy(dbuf, ctime(&now));
  331.     *index(dbuf, '\n') = '\0';
  332.     if (macvalue('d', CurEnv) == NULL)
  333.         define('d', dbuf, CurEnv);
  334.     p = newstr(arpadate(dbuf));
  335.     if (macvalue('a', CurEnv) == NULL)
  336.         define('a', p, CurEnv);
  337.     define('b', p, CurEnv);
  338. }
  339. /*
  340. **  OPENXSCRIPT -- Open transcript file
  341. **
  342. **    Creates a transcript file for possible eventual mailing or
  343. **    sending back.
  344. **
  345. **    Parameters:
  346. **        e -- the envelope to create the transcript in/for.
  347. **
  348. **    Returns:
  349. **        none
  350. **
  351. **    Side Effects:
  352. **        Creates the transcript file.
  353. */
  354.  
  355. void
  356. openxscript(e)
  357.     register ENVELOPE *e;
  358. {
  359.     register char *p;
  360.     int fd;
  361.  
  362. #ifdef LOG
  363.     if (LogLevel > 19)
  364.         syslog(LOG_DEBUG, "%s: openx%s", e->e_id, e->e_xfp == NULL ? "" : " (no)");
  365. #endif /* LOG */
  366.     if (e->e_xfp != NULL)
  367.         return;
  368.     p = queuename(e, 'x');
  369.     fd = open(p, O_WRONLY|O_CREAT, 0644);
  370.     if (fd < 0)
  371.         syserr("Can't create %s", p);
  372.     else
  373.         e->e_xfp = fdopen(fd, "w");
  374. }
  375. /*
  376. **  CLOSEXSCRIPT -- close the transcript file.
  377. **
  378. **    Parameters:
  379. **        e -- the envelope containing the transcript to close.
  380. **
  381. **    Returns:
  382. **        none.
  383. **
  384. **    Side Effects:
  385. **        none.
  386. */
  387.  
  388. static void
  389. closexscript(e)
  390.     register ENVELOPE *e;
  391. {
  392.     if (e->e_xfp == NULL)
  393.         return;
  394.     (void) fclose(e->e_xfp);
  395.     e->e_xfp = NULL;
  396. }
  397. /*
  398. **  SETSENDER -- set the person who this message is from
  399. **
  400. **    Under certain circumstances allow the user to say who
  401. **    s/he is (using -f or -r).  These are:
  402. **    1.  The user's uid is zero (root).
  403. **    2.  The user's login name is in an approved list (typically
  404. **        from a network server).
  405. **    3.  The address the user is trying to claim has a
  406. **        "!" character in it (since #2 doesn't do it for
  407. **        us if we are dialing out for UUCP).
  408. **    A better check to replace #3 would be if the
  409. **    effective uid is "UUCP" -- this would require me
  410. **    to rewrite getpwent to "grab" uucp as it went by,
  411. **    make getname more nasty, do another passwd file
  412. **    scan, or compile the UID of "UUCP" into the code,
  413. **    all of which are reprehensible.
  414. **
  415. **    Assuming all of these fail, we figure out something
  416. **    ourselves.
  417. **
  418. **    Parameters:
  419. **        from -- the person we would like to believe this message
  420. **            is from, as specified on the command line.
  421. **
  422. **    Returns:
  423. **        none.
  424. **
  425. **    Side Effects:
  426. **        sets sendmail's notion of who the from person is.
  427. */
  428.  
  429. static char PostMaster[] = "postmaster";    /* for gcc */
  430.  
  431. void
  432. setsender(from)
  433.     char *from;
  434. {
  435.     register char **pvp;
  436.     char *realname = NULL;
  437.     register struct passwd *pw;
  438.     char buf[MAXNAME];
  439.     char pvpbuf[PSBUFSIZE];
  440.     extern char *FullName;
  441.  
  442.     if (tTd(45, 1))
  443.         printf("setsender(%s)\n", from == NULL ? "" : from);
  444.  
  445.     /*
  446.     **  Figure out the real user executing us.
  447.     **    Username can return errno != 0 on non-errors.
  448.     */
  449.  
  450.     if (QueueRun || OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
  451.         realname = from;
  452.     if (realname == NULL || realname[0] == '\0')
  453.         realname = username();
  454.  
  455.     /*
  456.     **  Determine if this real person is allowed to alias themselves.
  457.     */
  458.  
  459.     if (from != NULL)
  460.     {
  461.         if (!trusteduser(realname) && getuid() != geteuid() &&
  462.             index(from, '!') == NULL && getuid() != 0)
  463.         {
  464.             /* network sends -r regardless (why why why?) */
  465.             /* syserr("%s, you cannot use the -f flag", realname); */
  466.             from = NULL;
  467.         }
  468.     }
  469.  
  470.     SuprErrs = TRUE;
  471.     if (from == NULL || parseaddr(from, &CurEnv->e_from, 1, '\0') == NULL)
  472.     {
  473.         /* log garbage addresses for traceback */
  474.         if (from != NULL)
  475.         {
  476. #ifdef LOG
  477.             if (LogLevel >= 1)
  478.                 if (realname == from && RealHostName != NULL)
  479.                 syslog(LOG_NOTICE,
  480.                     "from=%s unparseable, received from %s",
  481.                     from, RealHostName);
  482.                 else
  483.                 syslog(LOG_NOTICE,
  484.                     "Unparseable username %s wants from=%s",
  485.                     realname, from);
  486. #endif /* LOG */
  487.         }
  488.         from = newstr(realname);
  489.         if (parseaddr(from, &CurEnv->e_from, 1, '\0') == NULL &&
  490.             parseaddr(PostMaster, &CurEnv->e_from, 1, '\0') == NULL)
  491.         {
  492.             syserr("setsender: can't even parse postmaster!");
  493.         }
  494.     }
  495.     else
  496.         FromFlag = TRUE;
  497.     CurEnv->e_from.q_flags |= QDONTSEND;
  498.     loweraddr(&CurEnv->e_from);
  499.     SuprErrs = FALSE;
  500.  
  501.     if (CurEnv->e_from.q_mailer == LocalMailer &&
  502.         (pw = getpwnam(CurEnv->e_from.q_user)) != NULL)
  503.     {
  504.         /*
  505.         **  Process passwd file entry.
  506.         */
  507.  
  508.  
  509.         /* extract home directory */
  510.         CurEnv->e_from.q_home = newstr(pw->pw_dir);
  511.         define('z', CurEnv->e_from.q_home, CurEnv);
  512.  
  513.         /* extract user and group id */
  514.         CurEnv->e_from.q_uid = pw->pw_uid;
  515.         CurEnv->e_from.q_gid = pw->pw_gid;
  516.  
  517.         /* if the user has given fullname already, don't redefine */
  518.         if (FullName == NULL)
  519.             FullName = macvalue('x', CurEnv);
  520.         if (FullName != NULL && FullName[0] == '\0')
  521.             FullName = NULL;
  522.  
  523.         /* extract full name from passwd file */
  524.         if (FullName == NULL && pw->pw_gecos != NULL &&
  525.             strcmp(pw->pw_name, CurEnv->e_from.q_user) == 0)
  526.         {
  527.             buildfname(pw->pw_gecos, CurEnv->e_from.q_user, buf);
  528.             if (buf[0] != '\0')
  529.                 FullName = newstr(buf);
  530.         }
  531.         if (FullName != NULL)
  532.             define('x', FullName, CurEnv);
  533.     }
  534.     else
  535.     {
  536.         if (CurEnv->e_from.q_home == NULL)
  537.             CurEnv->e_from.q_home = getenv("HOME");
  538.         CurEnv->e_from.q_uid = getuid();
  539.         CurEnv->e_from.q_gid = getgid();
  540.     }
  541.  
  542.     /*
  543.     **  Rewrite the from person to dispose of possible implicit
  544.     **    links in the net.
  545.     */
  546.  
  547.     pvp = prescan(from, '\0', pvpbuf);
  548.     if (pvp == NULL)
  549.     {
  550. #ifdef LOG
  551.         if (LogLevel >= 1)
  552.             syslog(LOG_NOTICE, "cannot prescan from (%s)", from);
  553. #endif /* LOG */
  554.         usrerr("cannot prescan from (%s)", from);
  555.         finis();
  556.     }
  557.     rewrite(pvp, 3);
  558.     rewrite(pvp, 1);
  559.     rewrite(pvp, 4);
  560.     cataddr(pvp, buf, sizeof buf);
  561.     define('f', newstr(buf), CurEnv);
  562.  
  563.     /* save the domain spec if this mailer wants it */
  564.     if (CurEnv->e_from.q_mailer != NULL &&
  565.         bitnset(M_CANONICAL, CurEnv->e_from.q_mailer->m_flags))
  566.     {
  567.         while (*pvp != NULL && strcmp(*pvp, "@") != 0)
  568.             pvp++;
  569.         if (*pvp != NULL)
  570.             CurEnv->e_fromdomain = copyplist(pvp, TRUE);
  571.     }
  572. }
  573. /*
  574. **  TRUSTEDUSER -- tell us if this user is to be trusted.
  575. **
  576. **    Parameters:
  577. **        user -- the user to be checked.
  578. **
  579. **    Returns:
  580. **        TRUE if the user is in an approved list.
  581. **        FALSE otherwise.
  582. **
  583. **    Side Effects:
  584. **        none.
  585. */
  586.  
  587. static bool
  588. trusteduser(user)
  589.     const char *user;
  590. {
  591.     register char **ulist;
  592.     extern char *TrustedUsers[];
  593.  
  594.     for (ulist = TrustedUsers; *ulist != NULL; ulist++)
  595.         if (strcmp(*ulist, user) == 0)
  596.             return (TRUE);
  597.     return (FALSE);
  598. }
  599.